`timescale 1ns / 1ps
//====================DDR �ռ����??===================
//ֻʹ�����е�һƬDDR,�ֳ�4���֣�ÿ��������Ϊһ��ƹ��buffer����Ϊ���л��������ݻ���
//ddr�ռ�:256*16Mbit = 536870912Byte = 512MBytes
//================������·��9361--->DDR--->TX2
//ddrд:wr_seg_1: WR_ADDR_BASE0 = 0    			     wr_seg_2��WR_ADDR_BASE1 = 128M = 128*1024*1024 = 134217728
//FDMAλ��128bit��ÿ��burst����Ϊ256==>ÿ��burst���ֽ���Ϊ256*128/8= 4096Bytes
//Ϊ������ö�д������ÿ��дDDR���ֽ�����ҪΪ4096Bytes��������
//fpgaÿ��д��2M�����ݷ���һ�ζ��ж�
//================������·��9361<---DDR<----TX2
//ddr��:rd_seg_1:RD_ADDR_BASE1 = 256M = 268435456      rd_seg_2: RD_ADDR_BASE2 = 384M = 384*1024*1024 = 402653184
//FDMAλ��128bit��ÿ��burst����Ϊ256==>ÿ��burst���ֽ���Ϊ256*128/8= 4096Bytes
//Ϊ������ö�д������ÿ�ζ�DDR���ֽ�����ҪΪ4096Bytes��������
//fpgaÿ�ζ�ȡ��2M�����ݷ���һ��д�ж�
//ONE_M_BYTES= 1048576,
//ONE_K_BYTES= 1024,
module fdma_controller#
(
	parameter  integer  ONE_K_BYTES= 1024,
	parameter  integer  ONE_M_BYTES   = 1048576,
//	parameter  integer  RD_SEG_DEEPTH    = 8*ONE_M_BYTES,//4*ONE_M_BYTES,//32*ONE_K_BYTES,// for 80M TX 40M RX(DUAL AD9364)
    parameter  integer  RD_SEG_DEEPTH    = 4*ONE_M_BYTES,//4*ONE_M_BYTES,//32*ONE_K_BYTES,// for 40M TX 40M RX(single AD9364)
    
//  parameter  integer  WR_SEG_DEEPTH    = 4*ONE_M_BYTES,//4*ONE_M_BYTES,//2*ONE_M_BYTES,//16*ONE_K_BYTES,// // for 80M TX 40M RX(DUAL AD9364)
    
//    parameter  integer  WR_SEG_DEEPTH    = 2*ONE_M_BYTES,//4*ONE_M_BYTES,//2*ONE_M_BYTES,//16*ONE_K_BYTES,//for 40M TX 20M RX(single AD9364)

//parameter  integer  WR_SEG_DEEPTH    = 2*ONE_M_BYTES,//4*ONE_M_BYTES,//2*ONE_M_BYTES,//16*ONE_K_BYTES,//for 40M TX 20M RX(single AD9364)   230522

parameter  integer  WR_SEG_DEEPTH    = 4*ONE_M_BYTES,//4*ONE_M_BYTES,//2*ONE_M_BYTES,//16*ONE_K_BYTES,//for 40M TX 40M RX(single AD9364)
    
//	parameter  integer  SEG_DEEPTH    = 4*ONE_M_BYTES,//2*ONE_M_BYTES,// 16*ONE_K_BYTES,// // for 80M TX 40M RX(DUAL AD9364)
	
//	parameter  integer  SEG_DEEPTH    = 2*ONE_M_BYTES,//2*ONE_M_BYTES,// 16*ONE_K_BYTES,// for 40M TX 20M RX(single AD9364)

//  parameter  integer  SEG_DEEPTH    = 2*ONE_M_BYTES,//2*ONE_M_BYTES,// 16*ONE_K_BYTES,// for 40M TX 20M RX(single AD9364)  230522
parameter  integer  SEG_DEEPTH    = 4*ONE_M_BYTES,//2*ONE_M_BYTES,// 16*ONE_K_BYTES,// for 40M TX 40M RX(single AD9364)
	
    parameter  integer  SEG_DEEPTH_HALF    = SEG_DEEPTH/2,
	parameter  integer  WR_ADDR_BASE1 = 0,
	parameter  integer  WR_ADDR_BASE2 = 134217728,
	parameter  integer  RD_ADDR_BASE1 = 268435456,
	parameter  integer  RD_ADDR_BASE2 = 402653184
)
(

//add 1pps
   
    input [64-1:0]          i_data_pps,
//----------------------------------------------------------

    
    
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_ui_clk,//100M  Fr DDR
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_ui_rstn,
	//-----------sensor write fifo signals--------------
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_sensor_wr_clk,  //40M Fr 9361
    (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_sensor_wr_en,   //9361дfifoʹ���ź�
	//(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input  [15:0]   		i_sensor_wr_data, //data Fr 9361   for 40M TX 40M RX(single AD9364)
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input  [63:0]   		i_sensor_wr_data, //data Fr 9361   for 40M TX 40M RX(single AD9364) for pps
    (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input  [63:0]   		i_sensor_wr_data_copy, //data Fr 9361   for 40M TX 40M RX(single AD9364) for pps
    output                W0_wr_full,    //by z
    	//***//(*mark_debug = "true"*)(* KEEP = "TRUE" *)input  [63:0]   		i_sensor_wr_data, //data Fr 9361  for 40M TX 40M RX(single AD9364)

	//----------fdma write ddr signals -------       
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  reg     		o_burst_wr_areq,       
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_burst_wr_en,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_burst_wr_last,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [31:0]  	    o_burst_wr_addr,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [127:0] 		o_burst_wr_data,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [31:0]  		o_burst_wr_size,
	 //----------sensor read fifo signals---------------
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_sensor_rd_clk, //40M Fr 9361
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_sensor_rd_en,  //9361��fifoʹ���ź�
    	//(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [31:0]  		o_sensor_rd_data,//data To 9361  λ��64-��32  // for 80M TX 40M RX(DUAL AD9364)
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [63:0]  		o_sensor_rd_data,//data To 9361  λ��64-��32  // for 40M TX 40M RX(single AD9364)
	
    (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output                  dac_fifo_underflow, //by z
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output                  dac_fifo_valid, //by z
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output                  dac_fifo_wr_full,//by z
	
	//----------fdma read ddr signals ------- 		
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  reg     		o_burst_rd_areq,       
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_burst_rd_en,
    (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input           		i_burst_rd_last,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [31:0]  		o_burst_rd_addr,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)input   [127:0]  	    i_burst_rd_data,
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  [31:0]  		o_burst_rd_size,
	//----------interrupt signals to TX2
	(*mark_debug = "FALSE"*)output       		    o_ReadReqInt,    //�ж�:���������� ��TX2
	(*mark_debug = "FALSE"*)output       		    o_WriteReqInt,   //�ж�:д�������� ��TX2
    (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  reg[31:0]     	o_NeedReadSeg,     //SegNum: 1  2  ��Ҫ��ȡ�Ķκ�
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  reg[31:0]     	o_NeedWriteSeg,    //SegNum: 1  2  ��Ҫд��Ķκ�??
	(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)output  reg[31:0]     	o_NeedReadSegGNSS_PPS    //SegNum: 1  2  ��Ҫд��Ķκ�??
    );
    localparam FIFO_DEPTH = 2048;//��дDDR��fifo���??
    localparam BURST_THR = 256; //����һ��DMAͻ����д������ 
    localparam BURST_DATA_WIDTH = 128;
    localparam BYTES_PER_BURST = BURST_THR*BURST_DATA_WIDTH/8;//4KByte
    //--------------------------------------------------------------------------------------
    //                           local variable definition 
    //--------------------------------------------------------------------------------------
   wire [10 : 0]W0_CanReadCnt;
   wire [11 : 0] R0_CanReadCnt; //by z
   reg W0_REQ;//request of write ddr flag
   reg R0_REQ;//request of read ddr flag
     //--------------------------------------------------------------------------------------
     //                          generate write/read DDR request 
     //--------------------------------------------------------------------------------------
    assign o_burst_wr_size = BURST_THR;//ÿ��ͻ��д�ĳ���
    assign o_burst_rd_size = BURST_THR;//ÿ��ͻ�����ĳ���
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg DownLinkEn;//����ʹ���ź�
    wire [31:0] R0_EmptySize;
    assign R0_EmptySize = FIFO_DEPTH*2-R0_CanReadCnt;//9361 to ddr �ɶ�����
    always@(posedge i_ui_clk)
    begin   
        if(!i_ui_rstn) begin
            W0_REQ    <= 0;
            R0_REQ    <= 0;
        end
        else begin
            W0_REQ    <= W0_CanReadCnt >= BURST_THR;//����fifo �ɶ�ȡ����������burst���ޣ�����дDDR���󣬴�FIFO������д��DDR
            R0_REQ    <= R0_EmptySize >= BURST_THR*2;//����fifo ��д������������burst���ޣ������DDR���󣬴�DDR������д��FIFO 
        end
    end
    localparam S_IDLE       = 4'b0000;    
    localparam S_W_REQ      = 4'b0001;     
    localparam S_WRITE      = 4'b0010;  
    localparam S_R_REQ      = 4'b0100;  
    localparam S_READ       = 4'b1000; 
    
    (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg [3:0]  cur_state;
    reg [3:0] next_state;
    always@(posedge i_ui_clk)begin
       if(!i_ui_rstn)cur_state<=S_IDLE;
       else cur_state<=next_state;
    end
    always@(*)begin
       next_state=cur_state;
       case(cur_state)
           S_IDLE:    begin 
                       if(W0_REQ)next_state = S_W_REQ;
                       else if(R0_REQ&DownLinkEn)next_state = S_R_REQ;
                   end
           S_W_REQ:next_state = S_WRITE;
           S_WRITE:if(i_burst_wr_last) next_state = S_IDLE;
           S_R_REQ:next_state = S_READ;
           S_READ:if(i_burst_rd_last) next_state = S_IDLE;
       endcase
    end
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //9361 --> DDR  --> interrupt --> tx2
    //���ݶ�ƫ���ź������ж��ź�
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    always@(posedge i_ui_clk)begin //дDDR�����ź�
       if(!i_ui_rstn) o_burst_wr_areq<=0;
       else begin
           if(cur_state==S_W_REQ)o_burst_wr_areq<=1;
           else if(cur_state==S_WRITE) o_burst_wr_areq<=0;
       end
    end
  (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg [31:0] m_WrOffset;//д��ַ�μ�ƫ��
  (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg wr_seg_1_full;
    always@(posedge i_ui_clk)begin//д��ַ������ÿ��д�����burst����
       if(!i_ui_rstn)begin  m_WrOffset<=0; wr_seg_1_full<=0; end
       else if(cur_state==S_WRITE) begin        
        if(i_burst_wr_last)begin
               if(m_WrOffset>=WR_SEG_DEEPTH-BYTES_PER_BURST)begin m_WrOffset<=0;  wr_seg_1_full<=~wr_seg_1_full;end        
               else m_WrOffset<=m_WrOffset + BYTES_PER_BURST;         
           end
       end
    end  
    assign o_burst_wr_addr = !wr_seg_1_full ? WR_ADDR_BASE1 + m_WrOffset : WR_ADDR_BASE2 + m_WrOffset; 
    //---------------------------------���ɽ����ź�-------------------- 
  (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg[1:0] seg_need_read_reg;//��Ҫ��ȡ�Ķκ�
   always@(posedge i_ui_clk)
   begin
    if(!i_ui_rstn)begin
       seg_need_read_reg<=0;
    end
    else begin
       if(wr_seg_1_full)
           seg_need_read_reg<=2'b01;
       else
          seg_need_read_reg<=2'b10;
    end
   end 
  (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg[1:0] seg_need_read_reg_old,seg_need_read_reg_old_d1;  //seg_need_read_reg_old_d1 for 1pps
   always@(posedge i_ui_clk)
   begin
       seg_need_read_reg_old <= seg_need_read_reg;
       seg_need_read_reg_old_d1<=seg_need_read_reg_old;  //seg_need_read_reg_old_d1 for 1pps
   end
   //������
  // (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[29-1:0]ReadReqCnt;
  (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[3-1:0]ReadReqCnt; //for 1pps

   always@(posedge i_ui_clk)
   begin
    if(!i_ui_rstn)begin
        ReadReqCnt <= 0;
        end
    else
       if(seg_need_read_reg_old != seg_need_read_reg)begin
        ReadReqCnt <= ReadReqCnt+1;
        end
   end 
   reg wr_seg_1_full_d1,wr_seg_1_full_d2;
   always@(posedge i_ui_clk)
   begin
      wr_seg_1_full_d1 <= wr_seg_1_full; 
      wr_seg_1_full_d2<=wr_seg_1_full_d1;
   end
    
   // always@(posedge i_ui_clk)
   // begin
   //    o_NeedReadSeg <= {ReadReqCnt,wr_seg_1_full_d2,seg_need_read_reg_old}; 
   // end  
   //�ж��ź�
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg ReadReqInt;
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[32-1:0] ReadReqIntHoldTime;//�жϱ���ʱ�䣬Ԥ������ֹ���ж�
   always@(posedge i_ui_clk)
   if(!i_ui_rstn)begin
     ReadReqInt<=0;
     ReadReqIntHoldTime<=0;
   end
   else begin
    ReadReqIntHoldTime<=ReadReqIntHoldTime+1;
    if(seg_need_read_reg_old != seg_need_read_reg)begin   ReadReqInt<=1;ReadReqIntHoldTime<=0; end
    else if(ReadReqIntHoldTime>1310720) ReadReqInt<=0;	
   end
   
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //������·д��һ��������������·
    //-------------------------------------------------------------------------    
    always@(posedge i_ui_clk)begin
       if(!i_ui_rstn)  DownLinkEn<=0;
        else if(m_WrOffset>=SEG_DEEPTH_HALF)  DownLinkEn<=1; //9361->DDRд��һ��������������·
    end 
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    //9361 <-- DDR  <-- interrupt <-- tx2
    //���ݶ�ƫ���ź������ж��ź�
    //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
    always@(posedge i_ui_clk)begin//��DDR�����ź�
       if(!i_ui_rstn) o_burst_rd_areq<=0; 
       else begin
           if(cur_state==S_R_REQ)o_burst_rd_areq<=1;
           else if(cur_state==S_READ) o_burst_rd_areq<=0;
       end
    end
   
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg rd_seg_1_empty;
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg [31:0] m_RdOffset;//����ַ�μ�ƫ��
    always@(posedge i_ui_clk)begin//����ַ������ÿ�ζ������burst����
       if(!i_ui_rstn)begin  m_RdOffset<=0; rd_seg_1_empty<=0; end
       else if(cur_state==S_READ) begin        
           if(i_burst_rd_last)begin
               if(m_RdOffset>=RD_SEG_DEEPTH-BYTES_PER_BURST)begin  m_RdOffset<=0; rd_seg_1_empty<=~rd_seg_1_empty;end
               else m_RdOffset<=m_RdOffset + BYTES_PER_BURST; 
           end
       end
    end
    assign o_burst_rd_addr = !rd_seg_1_empty ? RD_ADDR_BASE1 + m_RdOffset : RD_ADDR_BASE2 + m_RdOffset;
     //---------------------------------���ɽ����ź�------------------- 
  (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) reg[1:0] seg_need_write_reg;//��Ҫд��Ķκ�??
   always@(posedge i_ui_clk)
   begin
    if(!i_ui_rstn)begin
       seg_need_write_reg<=0;
    end
    else begin
       if(rd_seg_1_empty)
           seg_need_write_reg<=2'b01;
       else
          seg_need_write_reg<=2'b10;
    end
   end
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[1:0] seg_need_write_reg_old; 
   always@(posedge i_ui_clk)
   begin
       seg_need_write_reg_old <= seg_need_write_reg;
   end
   //д����
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[29-1:0] WriteReqCnt;
   always@(posedge i_ui_clk)
   begin
    if(!i_ui_rstn)begin
        WriteReqCnt <= 0;
        end
    else
       if(seg_need_write_reg_old != seg_need_write_reg)begin
        WriteReqCnt <= WriteReqCnt+1;
        end
   end
   reg rd_seg_1_empty_d1,rd_seg_1_empty_d2;
      always@(posedge i_ui_clk)
      begin
         rd_seg_1_empty_d1 <= rd_seg_1_empty; 
         rd_seg_1_empty_d2<=rd_seg_1_empty_d1;
      end
   always@(posedge i_ui_clk)
   begin     
      o_NeedWriteSeg <= {WriteReqCnt ,rd_seg_1_empty_d2,seg_need_write_reg_old};
   end
    //�ж��ź�
   (*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg WriteReqInt;
   reg[32-1:0] WriteReqIntHoldTime;//�жϱ���ʱ�䣬Ԥ������ֹ���ж�
   always@(posedge i_ui_clk)
   if(!i_ui_rstn)begin
     WriteReqInt<=0;
     WriteReqIntHoldTime<=0;
   end
   else begin
    WriteReqIntHoldTime<=WriteReqIntHoldTime+1;
    if(seg_need_write_reg_old != seg_need_write_reg)begin   WriteReqInt<=1;WriteReqIntHoldTime<=0; end
    else if(WriteReqIntHoldTime>1310720) WriteReqInt<=0;    
   end
   //---------------------------
   localparam DELAY=101;//by z
   reg [1-1:0] LocalWriteReqIntShift[DELAY-1:0];
   reg [1-1:0] LocalReadReqIntShift[DELAY-1:0];
   always@(posedge i_ui_clk)
   begin: shifter_always
           integer i;
           begin
           for(i=0;i<DELAY-1;i=i+1)
               begin
                    LocalWriteReqIntShift[i+1] <= LocalWriteReqIntShift[i];
                    LocalReadReqIntShift[i+1] <= LocalReadReqIntShift[i];
               end
           LocalWriteReqIntShift[0]<=WriteReqInt;
           LocalReadReqIntShift[0]<=ReadReqInt;
           end
   end
   assign o_ReadReqInt = LocalReadReqIntShift[100];
   assign o_WriteReqInt =  LocalWriteReqIntShift[100];
 //---------------------------����������fifo--------------------------//
//(*mark_debug = "true"*)(* KEEP = "TRUE" *) wire W0_wr_full;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) wire  R0_rd_empty;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) wire DatToDDR_empty;
// 9361--->DDR
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) wire[127:0] DatToDDR;//***
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) wire[127:0] GNSS_DatToDDR;//***

//-----------for 1pps
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)wire[63:0] DatToDDR_ProcByPPS_L;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)wire[63:0] DatToDDR_ProcByPPS_H;
assign DatToDDR_ProcByPPS_H = (DatToDDR[63:4]== 60'hEB905A5A5A5A146)  ?  i_data_pps : DatToDDR[63:0]; //EB905555AAAA146F BY Z
assign DatToDDR_ProcByPPS_L = (DatToDDR[127:68]== 60'hEB905A5A5A5A146) ? i_data_pps : DatToDDR[127:64];//EB905555AAAA146F BY Z

assign o_burst_wr_data = {DatToDDR_ProcByPPS_H,DatToDDR_ProcByPPS_L};


//-----------------------------
//assign o_burst_wr_data = {DatToDDR[15:0],DatToDDR[31:16],DatToDDR[47:32],DatToDDR[63:48],DatToDDR[79:64],DatToDDR[95:80],DatToDDR[111:96],DatToDDR[127:112]};  //by z   // for 40M TX 40M RX(DUAL AD9364)



 Sensor_DDR_FIFO Sensor_DDR_FIFO_INST (
  .rst(!i_ui_rstn),                   // input wire rst
  .wr_clk(i_sensor_wr_clk),         // input wire wr_clk
  .wr_en(i_sensor_wr_en),    				// input wire wr_en
  .din(i_sensor_wr_data),           // input wire [63: 0] din
  .full(W0_wr_full),                
  .wr_rst_busy(),
 								    
  .rd_clk(i_ui_clk),                  // input wire rd_clk
  .rd_en(i_burst_wr_en),              // input wire rd_en
  .dout(DatToDDR),                 // output wire [127 : 0] dout*** 
  .rd_data_count(W0_CanReadCnt),     // output wire [10 : 0] rd_data_count
  .empty(DatToDDR_empty),
  .rd_rst_busy()
);


 Sensor_DDR_FIFO Sensor_DDR_FIFO_INST_GNSS (
  .rst(!i_ui_rstn),                   // input wire rst
  .wr_clk(i_sensor_wr_clk),         // input wire wr_clk
  .wr_en(i_sensor_wr_en),    				// input wire wr_en
  .din(i_sensor_wr_data_copy),           // input wire [63: 0] din
  .full(),                
  .wr_rst_busy(),
 								    
  .rd_clk(i_ui_clk),                  // input wire rd_clk
  .rd_en(i_burst_wr_en),              // input wire rd_en
  .dout(GNSS_DatToDDR),                 // output wire [127 : 0] dout*** 
  .rd_data_count(),     // output wire [10 : 0] rd_data_count
  .empty(),
  .rd_rst_busy()
);

// DDR--->9361
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *) wire[127:0] DatFrDDR;
assign DatFrDDR = {i_burst_rd_data[63:0],i_burst_rd_data[127:64]};
//assign DatFrDDR = {i_burst_rd_data[127:64],i_burst_rd_data[63:0]}; //by z
DDR_Sensor_FIFO DDR_Sensor_FIFO_INST (
  .rst(!i_ui_rstn),              // input wire rst
  .wr_clk(i_ui_clk),                  // input wire wr_clk
  .din(DatFrDDR),              // input wire [127 : 0] din
  
  .wr_en(i_burst_rd_en),              // input wire wr_en
  .full(dac_fifo_wr_full),    //by z
  .wr_rst_busy(),
  .rd_clk(i_sensor_rd_clk),         // input wire rd_clk 
  .rd_en(i_sensor_rd_en),                  		// input wire rd_en
  .dout(o_sensor_rd_data),          // output wire [63 : 0] dout
  .empty(R0_rd_empty),              // output wire empty
  .rd_data_count(R0_CanReadCnt),  	// output wire [11 : 0] rd_data_count
  .valid(dac_fifo_valid),  //by z
  .underflow(dac_fifo_underflow),  //by z
  .rd_rst_busy()
  
);

//------------calculate timestamp for 1pps
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg wr_seg_1_full_flag;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[26-1:0] SampCnt;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[26-1:0] SampCntLock,SampCntLockTmp;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg [3:0]  pps_state;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[26-1:0] GNSSPPS_SampCntLock,GNSSPPS_SampCntLockTmp;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg [3:0]  GNSSpps_state;

(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)wire [8-1:0]m_DatToDDR_H,m_DatToDDR_L;
(*mark_debug = "FALSE"*)(* KEEP = "FALSE" *)reg[4-1:0]  m_ClkCnt;
always @(posedge i_ui_clk)
begin
     if(!i_ui_rstn)m_ClkCnt<=0;
     else m_ClkCnt<=m_ClkCnt+1;
end
assign m_DatToDDR_L = DatToDDR[127:127-7]==16'hEB90 ? 16'hEB90 : m_ClkCnt;
assign m_DatToDDR_H = DatToDDR[63:63-7]==16'hEB90 ? 16'hEB90 : m_ClkCnt;
always @(posedge i_ui_clk)
begin
    if(!i_ui_rstn)begin
        SampCntLock<=26'b11_1111_1111_1111_1111_1111_1111;
        SampCntLockTmp<=26'b11_1111_1111_1111_1111_1111_1111;
        pps_state<=0;
    end
    else begin
        if(pps_state==0)begin
            if((i_burst_wr_en==1) && ( DatToDDR[63:4]== 60'hEB905A5A5A5A146  || DatToDDR[127:68]== 60'hEB905A5A5A5A146))begin
                // if(DatToDDR[63:4]== 60'hEB905A5A5A5A146)
                //     // SampCntLockTmp<=SampCnt*2+1;
                //     // SampCntLockTmp<=(SampCnt*2+1)*4+DatToDDR[3:0];
                //     SampCntLockTmp<=((SampCnt<<3)+4);
                // else
                //     // SampCntLockTmp<=SampCnt*2; 
                //     // SampCntLockTmp<=(SampCnt*2)*4+DatToDDR[3:0];
                //     SampCntLockTmp<=((SampCnt<<3));
                
                if 		(DatToDDR[63:0]== 64'hEB905A5A5A5A1461)
                	SampCntLockTmp<=((SampCnt<<3)+5);
                else if (DatToDDR[63:0]== 64'hEB905A5A5A5A1462)
                	SampCntLockTmp<=((SampCnt<<3)+6);
                else if (DatToDDR[63:0]== 64'hEB905A5A5A5A1463)
                	SampCntLockTmp<=((SampCnt<<3)+7);
            	else if (DatToDDR[63:0]== 64'hEB905A5A5A5A1464)
                	SampCntLockTmp<=((SampCnt<<3)+8);

                
            	else if (DatToDDR[127:64]== 64'hEB905A5A5A5A1461)
                	SampCntLockTmp<=((SampCnt<<3)+1);
            	else if (DatToDDR[127:64]== 64'hEB905A5A5A5A1462)
                	SampCntLockTmp<=((SampCnt<<3)+2);
            	else if (DatToDDR[127:64]== 64'hEB905A5A5A5A1463)
                	SampCntLockTmp<=((SampCnt<<3)+3);
            	else if (DatToDDR[127:64]== 64'hEB905A5A5A5A1464)
                	SampCntLockTmp<=((SampCnt<<3)+4);

                pps_state<=1;
            end
        end
        else if(pps_state==1)begin//�ȴ��������??
            if(seg_need_read_reg_old != seg_need_read_reg)begin
                pps_state<=2;
                SampCntLock<=SampCntLockTmp;
            end  
        end
        else if(pps_state==2)begin
            if(seg_need_read_reg_old != seg_need_read_reg)begin//������ʱ�䱣��2M�ֽڳ���
                SampCntLock<=26'b11_1111_1111_1111_1111_1111_1111;
                SampCntLockTmp<=26'b11_1111_1111_1111_1111_1111_1111;
                pps_state<=0;
            end
        end
    end
end

// 参�?�上段，GNSS_PPS
always @(posedge i_ui_clk)
begin
    if(!i_ui_rstn)begin
        GNSSPPS_SampCntLock<=26'b11_1111_1111_1111_1111_1111_1111;
        GNSSPPS_SampCntLockTmp<=26'b11_1111_1111_1111_1111_1111_1111;
        GNSSpps_state<=0;
    end
    else begin
        if(GNSSpps_state==0)begin
            if((i_burst_wr_en==1) && ( GNSS_DatToDDR[63:4]== 60'hEB905A5A5A5A146  || GNSS_DatToDDR[127:68]== 60'hEB905A5A5A5A146))begin
                // if(DatToDDR[63:4]== 60'hEB905A5A5A5A146)
                //     // SampCntLockTmp<=SampCnt*2+1;
                //     // SampCntLockTmp<=(SampCnt*2+1)*4+DatToDDR[3:0];
                //     SampCntLockTmp<=((SampCnt<<3)+4);
                // else
                //     // SampCntLockTmp<=SampCnt*2; 
                //     // SampCntLockTmp<=(SampCnt*2)*4+DatToDDR[3:0];
                //     SampCntLockTmp<=((SampCnt<<3));
                
                if 		(GNSS_DatToDDR[63:0]== 64'hEB905A5A5A5A1461)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+5);
                else if (GNSS_DatToDDR[63:0]== 64'hEB905A5A5A5A1462)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+6);
                else if (GNSS_DatToDDR[63:0]== 64'hEB905A5A5A5A1463)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+7);
            	else if (GNSS_DatToDDR[63:0]== 64'hEB905A5A5A5A1464)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+8);

                
            	else if (GNSS_DatToDDR[127:64]== 64'hEB905A5A5A5A1461)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+1);
            	else if (GNSS_DatToDDR[127:64]== 64'hEB905A5A5A5A1462)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+2);
            	else if (GNSS_DatToDDR[127:64]== 64'hEB905A5A5A5A1463)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+3);
            	else if (GNSS_DatToDDR[127:64]== 64'hEB905A5A5A5A1464)
                	GNSSPPS_SampCntLockTmp<=((SampCnt<<3)+4);

                GNSSpps_state<=1;
            end
        end
        else if(GNSSpps_state==1)begin//�ȴ��������??
            if(seg_need_read_reg_old != seg_need_read_reg)begin
                GNSSpps_state<=2;
                GNSSPPS_SampCntLock<=GNSSPPS_SampCntLockTmp;
            end  
        end
        else if(GNSSpps_state==2)begin
            if(seg_need_read_reg_old != seg_need_read_reg)begin//������ʱ�䱣��2M�ֽڳ���
                GNSSPPS_SampCntLock<=26'b11_1111_1111_1111_1111_1111_1111;
                GNSSPPS_SampCntLockTmp<=26'b11_1111_1111_1111_1111_1111_1111;
                GNSSpps_state<=0;
            end
        end
    end
end

always@(posedge i_ui_clk)begin
       wr_seg_1_full_flag<=wr_seg_1_full;
end
always@(posedge i_ui_clk)
begin
 if(!i_ui_rstn)begin
        SampCnt<=0;
    end
    else begin   
        if(wr_seg_1_full_flag != wr_seg_1_full)  
              SampCnt<=0;               
        else if(i_burst_wr_en)begin              
              SampCnt<=SampCnt+1;
        end  
        else   SampCnt<=SampCnt;
    end
end

always@(posedge i_ui_clk)
begin
   o_NeedReadSeg <= {SampCntLock,ReadReqCnt,wr_seg_1_full_d2,seg_need_read_reg_old_d1}; 
   o_NeedReadSegGNSS_PPS <= {GNSSPPS_SampCntLock,ReadReqCnt,wr_seg_1_full_d2,seg_need_read_reg_old_d1}; 
end 
endmodule
